﻿var data, charts = [], piecharts = [], chartsource = [3, 4, 5, 6];
var colors = ["green", "purple", "orange", "lime", "red", "teal"];
var series, user, statinit = false, rememberme = false;
var handlers = [];

$(document).ready(function () {
    $(".dynamic-content").show();
    $("#linktabs, #charttabs").tabs();
    $("#municipalitydialog").dialog({ autoOpen: false, resizable: false, draggable: false,
        closeOnEscape: false, width: "400", height: "230"
    });
    $("#seriesdialog").dialog({ autoOpen: false, resizable: false, draggable: false,
        width: "270", height: "100"
    });
    $("#button-choose, #button-add").button({ disabled: true });
    $(".button-swap").button({ icons: { primary: "ui-icon-transferthick-e-w"} });
    google.load("visualization", "1.0", { packages: ["corechart"], callback: initializeModule });
});

function initializeModule() {
    var state = restoreState();
    if (state != null) {
        chartsource = state.chartsource;
        colors = state.colors;
    }

    series = [{ color: colors.pop()}];

    charts[0] = new google.visualization.ChartWrapper({
        chartType: "ComboChart",
        options: { width: 700, height: 400,
            title: chartsource[0] == 3 ? "Transaktioner total" : "Transaktion / 1000 borgere",
            vAxis: { title: "Antal", minValue: 0 },
            hAxis: { format: "MMM y", slantedText: true },
            animation: { easing: "out" },
            focusTarget: "category",
            seriesType: "line",
            series: series,
            fontName: '"Arial"',
            areaOpacity: 0.1
        },
        chartName: "Transaktioner",
        containerId: "transchart"
    });

    charts[1] = new google.visualization.ChartWrapper({
        chartType: "ComboChart",
        options: { width: 700, height: 400,
            title: chartsource[1] == 4 ? "Aktiveringer total" : "Aktiveringer / 1000 borgere",
            vAxis: { title: "Antal", minValue: 0 },
            hAxis: { format: "MMM y", slantedText: true },
            animation: { easing: "out" },
            focusTarget: "category",
            seriesType: "line",
            series: series,
            fontName: '"Arial"',
            areaOpacity: 0.1
        },
        chartName: "Aktiveringer",
        containerId: "aktchart"
    });

    charts[2] = new google.visualization.ChartWrapper({
        chartType: "ComboChart",
        options: { width: 700, height: 400, title: "Gennemførselsprocent",
            vAxis: { title: "Procent", minValue: 0, maxValue: 100 },
            hAxis: { format: "MMM y", slantedText: true },
            animation: { easing: "out" },
            focusTarget: "category",
            seriesType: "line",
            series: series,
            fontName: '"Arial"',
            areaOpacity: 0.1
        },
        containerId: "pctchart"
    });

    charts[3] = new google.visualization.ChartWrapper({
        chartType: "ComboChart",
        options: { width: 700, height: 400, title: "Gennemsnitlig gennemførselstid",
            vAxis: { title: "Sekunder" },
            hAxis: { format: "MMM y", slantedText: true },
            animation: { easing: "out" },
            focusTarget: "category",
            seriesType: "line",
            series: series,
            fontName: '"Arial"',
            areaOpacity: 0.1
        },
        containerId: "timechart"
    });

    $("#municipalitydialog").dialog("option", "buttons", {
        "Vælg": function () {
            var value = $(this).find("select").val();
            $(this).off("dialogclose");
            $(this).dialog("close");
            $("#button-choose").button("option", "disabled", true);
            $("#seriescontainer .series").remove();
            $("#seriesdialog option").prop("disabled", false);
            $("#seriesdialog option[value='" + value + "']").prop("disabled", true);
            $(".piepanel").hide();
            loadStatistics({ mainSeries: value });
        }
    }).on("dialogclose", function () { openMunicipalityDialog(); });

    if (state == null) {
        openMunicipalityDialog();
        $("#municipalitydialog select").blur();
    } else loadStatistics(state);
}

function openMunicipalityDialog(position) {
    if (position == null) position = { my: "center", at: "center", of: $("#charttabs") };
    $("#municipalitydialog").dialog("open").dialog("widget").position(position);
}

function loadStatistics(state) {
    user = state.mainSeries;

    var jsonData = $.ajax({
        url: "statdata.aspx",
        dataType: "json",
        async: false
    }).responseText;

    data = new google.visualization.DataTable(jsonData);
    data.sort([1, 2]);
    generateAggregateSeries(data);
    var chartview = new google.visualization.DataView(data);
    chartview.setRows(data.getFilteredRows([{ column: 0, value: user}]));

    chartview.setColumns([{ calc: makeDate, type: 'date' }, { sourceColumn: chartsource[0], label: user}]);
    charts[0].setDataTable(chartview.toDataTable());
    piecharts[0] = new google.visualization.ChartWrapper({
        chartType: "PieChart",
        dataTable: new google.visualization.DataView(data),
        options: { width: 350, height: 300, fontName: '"Arial"' },
        chartName: "Transaktioner",
        containerId: "transpie"
    });
    piecharts[0].getDataTable().setColumns([0, 3]);
    piecharts[1] = new google.visualization.ChartWrapper({
        chartType: "PieChart",
        dataTable: new google.visualization.DataView(data),
        options: { width: 350, height: 300, fontName: '"Arial"' },
        chartName: "Transaktioner / 1000 borgere",
        containerId: "transrelpie"
    });
    piecharts[1].getDataTable().setColumns([0, 7]);
    google.visualization.events.addListener(charts[0], "select", function () {
        if (charts[0].getChart().getSelection().length &&
                    charts[0].getChart().getSelection()[0].column == null) {
            if (updatePieCharts(0)) $("#tab1 .piepanel").show("slow");
            else $("#tab1 .piepanel").hide("slow");
        } else {
            $("#tab1 .piepanel").hide("slow");
        }
    });

    chartview.setColumns([{ calc: makeDate, type: 'date' }, { sourceColumn: chartsource[1], label: user}]);
    charts[1].setDataTable(chartview.toDataTable());
    piecharts[2] = new google.visualization.ChartWrapper({
        chartType: "PieChart",
        dataTable: new google.visualization.DataView(data),
        options: { width: 350, height: 300, fontName: '"Arial"' },
        chartName: "Aktiveringer",
        containerId: "aktpie"
    });
    piecharts[2].getDataTable().setColumns([0, 4]);
    piecharts[3] = new google.visualization.ChartWrapper({
        chartType: "PieChart",
        dataTable: new google.visualization.DataView(data),
        options: { width: 350, height: 300, fontName: '"Arial"' },
        chartName: "Aktiveringer / 1000 borgere",
        containerId: "aktrelpie"
    });
    piecharts[3].getDataTable().setColumns([0, 8]);
    google.visualization.events.addListener(charts[1], "select", function () {
        if (charts[1].getChart().getSelection().length &&
                    charts[1].getChart().getSelection()[0].column == null) {
            if (updatePieCharts(1)) $("#tab2 .piepanel").show("slow");
            else $("#tab2 .piepanel").hide("slow");
        } else {
            $("#tab2 .piepanel").hide("slow");
        }
    });

    chartview.setColumns([{ calc: makeDate, type: 'date' }, { sourceColumn: chartsource[2], label: user}]);
    charts[2].setDataTable(chartview.toDataTable());

    chartview.setColumns([{ calc: makeDate, type: 'date' }, { sourceColumn: chartsource[3], label: user}]);
    charts[3].setDataTable(chartview.toDataTable());

    $(".userlabel").html(user);
    for (var i = 0; i < charts.length; i++) charts[i].draw();

    if (!statinit) initializeStatContent(state);

    $("#button-choose").button("option", "disabled", false);
}

function initializeStatContent(state) {
    statinit = true;
    $("#municipalitydialog").dialog("option", "closeOnEscape", true);
    $("#button-choose").click(function () {
        openMunicipalityDialog({ my: "left top", at: "left top", of: $(this) });
    });
    $("#charttabs").on("tabsselect", function (event, ui) {
        if (ui.index < charts.length) redrawChart(ui.index);
    }).find(".ui-widget-content").show();
    $("#seriesdialog select").change(function () {
        if ($("#seriescontainer .series").length == 4)
            $("#button-add").button("option", "disabled", true);
        addSeries($(this).val());
        var current = $("#charttabs").tabs("option", "selected");
        if (current < charts.length) redrawChart(current);
        $("#seriescontainer").append(createSeriesElement($(this).val()));
        $("#seriesdialog").dialog("close");
        $(this).find("option[value='" + $(this).val() + "']").prop("disabled", true);
    }).blur(function () {
        $("#seriesdialog").dialog("close");
    });
    $("#button-add").button("option", "disabled", false).click(function () {
        $("#seriesdialog option").first().prop("selected", "selected");
        $("#seriesdialog").dialog("open").dialog("widget")
                    .position({ my: "left top", at: "left top", of: $("#button-add") });
    });
    $(".button-swap").click(function () {
        swapChartData($(this));
    });
    $("#checkbox-avg").change(function () {
        if ($(this).prop("checked"))
            addSeries("Landsgennemsnit", { color: "blue", type: "area", visibleInLegend: false });
        else removeSeries("Landsgennemsnit", true);
    });
    $("#checkbox-remember").change(function () {
        if ($(this).prop("checked")) rememberme = true;
        else clearCookies();
    });
    $(window).unload(function () {
        if (rememberme) saveState();
    });

    // Restore a saved state.
    if (state.altSeries) {
        $("#municipalitydialog").off("dialogclose");
        $("#seriesdialog option[value='" + state.mainSeries + "']").prop("disabled", true);
        $("#checkbox-remember").prop("checked", true);
        $("#checkbox-remember").trigger("change");
        if (state.altSeries[0] != "") {
            for (var i = 0; i < state.altSeries.length; i++)
                $("#seriesdialog select").val(state.altSeries[i]).trigger("change");
        }
        if (state.tabs[0] != null) {
            for (var i = 0; i < state.tabs.length; i++) {
                handlers[state.tabs[i].index] = google.visualization.events.addListener(
                charts[state.tabs[i].index], "ready", (function (tab) {
                    return function () {
                        charts[tab.index].getChart().setSelection([{ row: tab.row}]);
                        google.visualization.events.trigger(charts[tab.index], "select");
                        google.visualization.events.removeListener(handlers[tab.index]);
                    }
                })(state.tabs[i]));
            }
        }
        if (state.showAverage == "true") {
            $("#checkbox-avg").prop("checked", true);
            $("#checkbox-avg").trigger("change");
        }
        $("#charttabs").tabs("option", "selected", state.activeTab);
        redrawChart(state.activeTab);
    }
}

function createSeriesElement(label) {
    return $("<div class='series'>" + label + "</div>")
            .append($("<div class='button-remove' style='float:right;margin:2px;'></div>")
                .button({ text: false, icons: { primary: "ui-icon-close"} })
                    .click(function () {
                        $(this).parent().remove();
                        removeSeries(label);
                        var current = $("#charttabs").tabs("option", "selected");
                        if (current < charts.length) redrawChart(current);
                        $("#button-add").button("option", "disabled", false);
                        $("#seriesdialog select").find("option[value='" + label + "']")
                            .prop("disabled", false);
                    })
                );
}

function redrawChart(chartIndex) {
    if (charts[chartIndex].getChart() == null)
        charts[chartIndex].draw();
    else {
        var selection = charts[chartIndex].getChart().getSelection();
        charts[chartIndex].draw();
        if (selection.length) {
            charts[chartIndex].getChart().setSelection(selection);
            if (selection[0].column == null && (chartIndex == 0 || chartIndex == 1))
                updatePieCharts(chartIndex);
        }
    }
}

function makeDate(dt, row) {
    return new Date(dt.getValue(row, 1), dt.getValue(row, 2) - 1);
}

function addSeries(label, seriesobj) {
    var rows = data.getFilteredRows([{ column: 0, value: label}]);
    for (var ci = 0; ci < charts.length; ci++) {
        var dt = charts[ci].getDataTable();
        var dtmin = 0, rowsmin = 0;
        while (dtmin < dt.getNumberOfRows() && rowsmin < rows.length) {
            if (dt.getValue(dtmin, 0) < makeDate(data, rows[rowsmin])) dtmin++;
            else if (dt.getValue(dtmin, 0) > makeDate(data, rows[rowsmin])) rowsmin++;
            else break;
        }
        if (dtmin == dt.getNumberOfRows() || rowsmin == rows.length) return;
        dt.addColumn("number", label);
        for (var i = 0; i < dtmin; i++)
            dt.setValue(i, dt.getNumberOfColumns() - 1, 0);
        for (var i = 0; i + dtmin < dt.getNumberOfRows() && i + rowsmin < rows.length; i++)
            dt.setValue(i + dtmin, dt.getNumberOfColumns() - 1, data.getValue(rows[i + rowsmin], chartsource[ci]));
    }
    if (seriesobj != null) series.push(seriesobj);
    else series.push({ color: colors.pop() });
}

function removeSeries(label, discardColor) {
    var dt = charts[0].getDataTable();
    for (var i = 2; i < dt.getNumberOfColumns(); i++) {
        if (dt.getColumnLabel(i) == label) {
            for (var ci = 0; ci < charts.length; ci++) {
                dt = charts[ci].getDataTable();
                dt.removeColumn(i);
            }
            if (!discardColor) colors.push(series.splice(i - 1, 1)[0].color);
            else series.splice(i - 1, 1);
            break;
        }
    }
}

function updatePieCharts(chartIndex) {
    var row = charts[chartIndex].getChart().getSelection()[0].row;
    if (!charts[chartIndex].getDataTable().getValue(row, 1))
        return false;
    if (chartIndex == 0) {
        updateSinglePie(piecharts[0], charts[0], row);
        updateSinglePie(piecharts[1], charts[0], row);
    } else if (chartIndex == 1) {
        updateSinglePie(piecharts[2], charts[1], row);
        updateSinglePie(piecharts[3], charts[1], row);
    }
    return true;
}

function updateSinglePie(pie, c, r) {
    var dt = c.getDataTable();
    var date = dt.getValue(r, 0);
    pie.setOption("title", pie.getChartName() + " for " + formatDate(date));
    pie.setOption("colors", getColorsInUse());
    var rows = [];
    for (var i = 1; i < dt.getNumberOfColumns(); i++) {
        if (series[i - 1].visibleInLegend != null && !series[i - 1].visibleInLegend) continue;
        var row = selectDataRow(dt.getColumnLabel(i), date);
        if (row != null) rows.push(row);
        else pie.getOption("colors").splice(i - 1, 1);
    }
    pie.getDataTable().setRows(rows);
    pie.draw();
}

function getColorsInUse() {
    var c = [];
    for (var i = 0; i < series.length; i++)
        if (series[i].visibleInLegend == null || series[i].visibleInLegend)
            c.push(series[i].color);
    return c;
}

function swapChartData($btn) {
    $btn.button("option", "disabled", true);
    var i;
    if ($btn.parents("#tab1").length) {
        i = 0;
        chartsource[i] = 10 - chartsource[i];
    } else if ($btn.parents("#tab2").length) {
        i = 1;
        chartsource[i] = 12 - chartsource[i];
    } else return;
    var selection = charts[i].getChart().getSelection();
    if (chartsource[i] == 7 || chartsource[i] == 8)
        charts[i].setOption("title", charts[i].getChartName() + " / 1000 borgere");
    else
        charts[i].setOption("title", charts[i].getChartName() + " total");
    var dt = charts[i].getDataTable();
    for (var c = 1; c < dt.getNumberOfColumns(); c++) {
        for (var r = 0; r < dt.getNumberOfRows(); r++) {
            var row = selectDataRow(dt.getColumnLabel(c), dt.getValue(r, 0));
            if (row != null) dt.setValue(r, c, data.getValue(row, chartsource[i]));
            else dt.setValue(r, c, 0);
        }
    }
    charts[i].setOption("animation.duration", "500");
    charts[i].draw();
    charts[i].setOption("animation.duration", "0");
    setTimeout(function () {
        $btn.button("option", "disabled", false);
        charts[i].getChart().setSelection(selection);
    }, 550);
}

function selectDataRow(label, date) {
    var rows = data.getFilteredRows([{ column: 0, value: label },
            { column: 1, value: date.getFullYear() },
            { column: 2, value: date.getMonth() + 1}]);
    if (rows.length) return rows[0];
    else return null;
}

function formatDate(date) {
    var yr = date.getFullYear();
    switch (date.getMonth()) {
        case 0: return "januar " + yr;
        case 1: return "februar " + yr;
        case 2: return "marts " + yr;
        case 3: return "april " + yr;
        case 4: return "maj " + yr;
        case 5: return "juni " + yr;
        case 6: return "juli " + yr;
        case 7: return "august " + yr;
        case 8: return "september " + yr;
        case 9: return "oktober " + yr;
        case 10: return "november " + yr;
        case 11: return "december " + yr;
    }
}

function generateAggregateSeries(data) {
    // Generating the average.
    var avgrows = [];
    var avgr = ["Landsgennemsnit", data.getValue(0, 1), data.getValue(0, 2)];
    for (var col = 3; col < data.getNumberOfColumns(); col++) avgr[col] = 0;
    var n = 0;
    for (var row = 0; row < data.getNumberOfRows(); row++) {
        if (avgr[1] != data.getValue(row, 1) || avgr[2] != data.getValue(row, 2)) {
            for (var col = 3; col < data.getNumberOfColumns(); col++) {
                avgr[col] = toFixed(avgr[col] / n, 2);
            }
            avgrows.push(avgr.slice(0));
            avgr = ["Landsgennemsnit", data.getValue(row, 1), data.getValue(row, 2)];
            for (var col = 3; col < data.getNumberOfColumns(); col++) avgr[col] = 0;
            n = 0;
        }
        for (var col = 3; col < data.getNumberOfColumns(); col++)
            avgr[col] += data.getValue(row, col);
        n++;
    }
    for (var col = 3; col < data.getNumberOfColumns(); col++)
        avgr[col] = toFixed(avgr[col] / n, 2);
    avgrows.push(avgr);
    data.addRows(avgrows);
}

function toFixed(num, x) {
    num *= 10 * x;
    num |= 0;
    return num / (10 * x);
}

function saveState() {
    // Main series.
    var state = [];
    state.push(user);
    
    // Alternate series.
    var altSeries = [];
    $("#seriescontainer > .series").each(function () { altSeries.push($(this).text()); });
    state.push(altSeries.join());

    // Color array.
    state[2] = [];
    for (var i = 0; i < colors.length; i++) state[2].push(colors[i]);
    for (var i = series.length - 1; i >= 0; i--)
        if (series[i].visibleInLegend == null || series[i].visibleInLegend)
            state[2].push(series[i].color);
    state[2] = state[2].join();

    // The chartsource array.
    state.push(chartsource.join());

    // Active tab.
    state.push($("#charttabs").tabs("option", "selected"));

    // What rows are selected (if any) on what tabs.
    var tabs = [];
    for (var i = 0; i < charts.length; i++)
        if (charts[i].getChart().getSelection().length && charts[i].getChart().getSelection()[0].column == null)
            tabs.push(i + ":" + charts[i].getChart().getSelection()[0].row);
    state.push(tabs.join());

    // Whether to show the average.
    state.push($("#checkbox-avg").prop("checked"));

    var now = new Date();
    var expiryDate = now.getMonth() < 10 ?
        new Date(now.getFullYear(), now.getMonth() + 2, now.getDate()) :
        new Date(now.getFullYear() + 1, now.getMonth() - 10, now.getDate());
    document.cookie = "state=" + state.join("+") + ";expires=" + expiryDate.toGMTString();
}

function restoreState() {
    var start = document.cookie.indexOf("state=");
    if (start < 0) return null;
    var end = document.cookie.indexOf(";", start);
    var state = document.cookie.substr(start + 6, document.cookie.length - end).split("+");
    if (state[0] == "0") return null;
    var obj = {};
    obj.mainSeries = state[0];
    obj.altSeries = state[1].split(",");
    obj.colors = state[2].split(",");
    obj.chartsource = $.map(state[3].split(","), function (val, i) { return parseInt(val); });
    obj.activeTab = parseInt(state[4]);
    obj.tabs = $.map(state[5].split(","), function (val, i) {
        if (val == "") return null;
        var tab = val.split(":");
        return { index: parseInt(tab[0]), row: parseInt(tab[1]) };
    });
    obj.showAverage = state[6];
    return obj;
}

function clearCookies() {
    var epoch = new Date(0);
    document.cookie = "state=0;expires=" + epoch.toGMTString();
    rememberme = false;
}
